package com.example.lijuan.myapplication.Util;

import android.content.Context;
import android.location.Location;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.location.LocationManagerProxy;
import com.amap.api.location.LocationProviderProxy;

import java.util.Iterator;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * Class com.sita.bike.utils is for
 *
 * @author xiaodong on 15/4/22.
 */
public class LocationController {
    private static final String TAG = LocationController.class.getSimpleName();
    private ConcurrentHashMap<Integer, LocationChangeListener> mListenerMap;
    private int mMapStartSequence = 100;
    private int mMapEndSequence = 200;
    private AtomicInteger mMapSequence;
    private ExecutorService executorService;
    private Context mContext;
    private boolean initialized;
    private Future<?> taskFuture;
    private LocationManagerProxy locationManager;

    private LocationController() {
        mMapSequence = new AtomicInteger(mMapStartSequence);
        mListenerMap = new ConcurrentHashMap<Integer, LocationChangeListener>();
        executorService = Executors.newSingleThreadExecutor();
    }

    /**
     * Use <code>GlobalContext.getLocationController()</code> instead
     */
    public static LocationController getInstance() {

        return Loader.INSTANCE;
    }

    public AMapLocation getLastKnownLocation() {
        return locationManager.getLastKnownLocation(LocationProviderProxy.AMapNetwork);
    }

    public int registerListener(LocationChangeListener listener) {
        int nextSeq = mMapSequence.incrementAndGet();
        if (nextSeq > mMapEndSequence) {
            nextSeq = mMapStartSequence;
        }
        mListenerMap.put(nextSeq, listener);
        Log.d(TAG, "register LocationChangeListener with id " + nextSeq);
        return nextSeq;
    }

    public void unregisterListener(int idx) {
        mListenerMap.remove(idx);

        Log.d(TAG, "unregister LocationChangeListener with id " + idx);
    }

    public void start(Context context) {
        mContext = context;
        locationManager = LocationManagerProxy.getInstance(mContext);
        if (!initialized) {
            taskFuture = executorService.submit(new LocationMonitor(mContext));
            initialized = true;
            Log.d(TAG, "Location controller started!");
        }
    }

    public void destroy() {
        if (taskFuture != null && !taskFuture.isCancelled()) {
            taskFuture.cancel(true);
        }
        if (taskFuture != null) {
            executorService.shutdown();
        }
        mListenerMap.clear();
        initialized = false;
        Log.d(TAG, "Location controller destroyed!");
    }

    private static class Loader {
        static LocationController INSTANCE = new LocationController();
    }

    private class LocationMonitor implements Runnable {

        Context mContext;

        private LocationMonitor(Context context) {
            mContext = context;
        }

        @Override
        public void run() {
            locationManager.requestLocationData(LocationProviderProxy.AMapNetwork, Constants.TIMEOUT, Constants.LOCATION_ACCURACY, new AMapLocationListener() {
                @Override
                public void onLocationChanged(AMapLocation aMapLocation) {
                    if (aMapLocation != null) {
                        Log.d(TAG, "Location controller get a new location=[" + aMapLocation + "]!");

                        Iterator<Map.Entry<Integer, LocationChangeListener>> it = mListenerMap.entrySet().iterator();
                        while (it.hasNext()) {
                            Map.Entry<Integer, LocationChangeListener> entry = it.next();
                            int key = entry.getKey();
                            LocationChangeListener listener = entry.getValue();
                            listener.notifyLocation(aMapLocation);
                            Log.d(TAG, "Location controller notify new location to " + key + ", " + listener + "!");
                        }
                    }
                }

                @Deprecated
                @Override
                public void onLocationChanged(Location location) {

                }

                @Override
                public void onStatusChanged(String provider, int status, Bundle extras) {

                }


                @Override
                public void onProviderEnabled(String provider) {

                }

                @Override
                public void onProviderDisabled(String provider) {
                    Toast.makeText(mContext, "open gps", Toast.LENGTH_SHORT).show();
                }
            });
        }
    }
}
